package render;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL30;
import org.lwjgl.util.glu.GLU;
/*
 * This is a class I am using to experiment with learning the open gl rendering code.
 * It is derived from the quad tutorials at  http://lwjgl.org/wiki/index.php?title=The_Quad_with_DrawElements
 */
public class RenderQuad {

	private int vertexCount;
	private int vaoId = 0;
	private int vboId = 0;
	private int vbocId= 0;
	
	private float scale=0.5f;
	private int indicesCount=0;
	private int vboiId;
	
	private int vsId =0;
	private int fsId =0;
	private int pId =0;
	
	public RenderQuad()
	{
			
	}
	
	
	public void setupQuad()
	{
		
		
		
		float [] vertices ={
				
				
				-1.0f,1.0f,0f,
				-1.0f,-1.0f,0f,
				1.0f,-1.0f,0f,
				1.0f,1.0f,0f
				
		};
		
		for (int v1 =0;v1< vertices.length;v1++)
		{
			vertices[v1]*= scale;
		}//scale quad with value of scale
		
		FloatBuffer verticesBuffer = BufferUtils.createFloatBuffer(vertices.length);
		verticesBuffer.put(vertices);
		verticesBuffer.flip();
		
		float[] colors = {
				1f, 0f, 0f, 1f,
				0f, 1f, 0f, 1f,
				0f, 0f, 1f, 1f,
				1f, 1f, 1f, 1f,
		};
		FloatBuffer colorsBuffer = BufferUtils.createFloatBuffer(colors.length);
		colorsBuffer.put(colors);
		colorsBuffer.flip();
		
		// OpenGL expects to draw vertices in counter clockwise order by default
		byte[] indices = {
				0, 1, 2,
				2, 3, 0
		};
		indicesCount = indices.length;
		ByteBuffer indicesBuffer = BufferUtils.createByteBuffer(indicesCount);
		indicesBuffer.put(indices);
		indicesBuffer.flip();
		
		// Create a new Vertex Array Object in memory and select it (bind)
		vaoId = GL30.glGenVertexArrays();
		GL30.glBindVertexArray(vaoId);
		
		// Create a new Vertex Buffer Object in memory and select it (bind) - VERTICES
		vboId = GL15.glGenBuffers();
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vboId);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, verticesBuffer, GL15.GL_STATIC_DRAW);
		GL20.glVertexAttribPointer(0, 4, GL11.GL_FLOAT, false, 0, 0);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		
		// Create a new VBO for the indices and select it (bind) - COLORS
		vbocId = GL15.glGenBuffers();
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vbocId);
		GL15.glBufferData(GL15.GL_ARRAY_BUFFER, colorsBuffer, GL15.GL_STATIC_DRAW);
		GL20.glVertexAttribPointer(1, 4, GL11.GL_FLOAT, false, 0, 0);
		GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
		
		// Deselect (bind to 0) the VAO
		GL30.glBindVertexArray(0);
		
		// Create a new VBO for the indices and select it (bind) - INDICES
		vboiId = GL15.glGenBuffers();
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);
		GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indicesBuffer, GL15.GL_STATIC_DRAW);
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
	}//end renderQuad
	
	public int loadShader(String filename, int type)
	{	//loadShader, fragement shader, and vertex shader
		//barrowed from the tutorial for colored quads at
		//http://lwjgl.org/wiki/index.php?title=The_Quad_colored#Vertex_Shader
		
		StringBuilder shaderSource = new StringBuilder();
		int shaderID = 0;
		
		try{
			BufferedReader reader = new BufferedReader(new FileReader(filename));
			String line;
			while ((line = reader.readLine())!= null)
			{
				shaderSource.append(line).append("\n");
			}
			reader.close();
		} catch (IOException e){
			System.err.println("Could not read file.");
			e.printStackTrace();
			System.exit(-1);
		}
		
		shaderID = GL20.glCreateShader(type);
		GL20.glShaderSource(shaderID, shaderSource);
		GL20.glCompileShader(shaderID);
		
		return shaderID;
	}
	
	protected void setupShaders()
	{
int errorCheckValue = GL11.glGetError();
		
		// Load the vertex shader
		vsId = this.loadShader("src/thequad/vertex.glsl", GL20.GL_VERTEX_SHADER);
		// Load the fragment shader
		fsId = this.loadShader("src/thequad/fragment.glsl", GL20.GL_FRAGMENT_SHADER);
		
		// Create a new shader program that links both shaders
		pId = GL20.glCreateProgram();
		GL20.glAttachShader(pId, vsId);
		GL20.glAttachShader(pId, fsId);
		GL20.glLinkProgram(pId);

		// Position information will be attribute 0
		GL20.glBindAttribLocation(pId, 0, "in_Position");
		// Color information will be attribute 1
		GL20.glBindAttribLocation(pId, 1, "in_Color");
		
		GL20.glValidateProgram(pId);
		
		errorCheckValue = GL11.glGetError();
		if (errorCheckValue != GL11.GL_NO_ERROR) {
			System.out.println("ERROR - Could not create the shaders:" + GLU.gluErrorString(errorCheckValue));
			System.exit(-1);
		}
	}
	
	public void renderQuad()
	{
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
		
		GL20.glUseProgram(pId);
		
		// Bind to the VAO that has all the information about the vertices
		GL30.glBindVertexArray(vaoId);
		GL20.glEnableVertexAttribArray(0);
		GL20.glEnableVertexAttribArray(1);
		
		// Bind to the index VBO that has all the information about the order of the vertices
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, vboiId);
		
		// Draw the vertices
		GL11.glDrawElements(GL11.GL_TRIANGLES, indicesCount, GL11.GL_UNSIGNED_BYTE, 0);
		
		// Put everything back to default (deselect)
		GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
		GL20.glDisableVertexAttribArray(0);
		GL20.glDisableVertexAttribArray(1);
		GL30.glBindVertexArray(0);
		GL20.glUseProgram(0);
	}//end renderQuad
	
	public void destroyQuad()
	{
		//barrowed from the tutorial
		
		// Delete the shaders
				GL20.glUseProgram(0);
				GL20.glDetachShader(pId, vsId);
				GL20.glDetachShader(pId, fsId);
				
				GL20.glDeleteShader(vsId);
				GL20.glDeleteShader(fsId);
				GL20.glDeleteProgram(pId);
				
				// Select the VAO
				GL30.glBindVertexArray(vaoId);
				
				// Disable the VBO index from the VAO attributes list
				GL20.glDisableVertexAttribArray(0);
				GL20.glDisableVertexAttribArray(1);
				
				// Delete the vertex VBO
				GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
				GL15.glDeleteBuffers(vboId);
				
				// Delete the color VBO
				GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
				GL15.glDeleteBuffers(vbocId);
				
				// Delete the index VBO
				GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
				GL15.glDeleteBuffers(vboiId);
				
				// Delete the VAO
				GL30.glBindVertexArray(0);
				GL30.glDeleteVertexArrays(vaoId);
				
		
	}


	/**
	 * @return the scale
	 */
	public float getScale() {
		return scale;
	}


	/**
	 * @param scale the scale to set
	 */
	public void setScale(float scale) {
		this.scale = scale;
	}
	
}//end renderquad
